package com.ruoyi.web.admin.data.command;

import com.ruoyi.common.core.domain.entity.AppUser;
import com.ruoyi.system.domain.SysDevice;
import com.ruoyi.system.domain.SysDeviceLocation;
import com.ruoyi.system.service.IAppUserService;
import com.ruoyi.system.service.ISysDeviceLocationService;
import com.ruoyi.system.service.ISysDeviceService;
import com.ruoyi.web.admin.data.Constants;
import com.ruoyi.web.admin.data.utils.CommonUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 位置信息上报命令处理器
 *
 * @author 10100
 */
@Component
public class ReportLocationCommandHandler implements CommandHandler {

    private static final Logger log = LoggerFactory.getLogger(ReportLocationCommandHandler.class);

    @Resource
    private ISysDeviceService sysDeviceService;

    @Resource
    private ISysDeviceLocationService deviceLocationService;

    @Resource
    private IAppUserService appUserService;

    @Override
    public String handle(String deviceId, String iccid, String recordId, String command,
                         String type, String timestamp, String length, String body) {
        log.info("设备主动[{}]位置信息上报：{}", deviceId, body);

        try {
            SysDevice device = sysDeviceService.selectSysDeviceByeIdentifier(deviceId);
            if (device != null) {
                // 解析位置数据
                SysDeviceLocation location = parseLocationData(device, body, timestamp);
                if (location != null) {
                    deviceLocationService.insertSysDeviceLocation(location);
                }

                device.setConnectionStatus("1");
                device.setLastHeartbeatTime(new Date());
                sysDeviceService.updateSysDevice(device);
            } else {
                // 设备不存在，创建新设备记录
                log.info("设备[{}]不存在，健康数据忽略", deviceId);
                return null;
            }
        } catch (Exception e) {
            log.error("设备[{}]位置信息处理失败：{}", deviceId, e.getMessage(), e);
        }

        // 构建响应格式
        String responseBody = "0";
        return "[" + deviceId + "," +
                iccid + "," +
                CommonUtils.generateSerialNumber() + "," +
                command + "," +
                Constants.REPORT_RESPONSE + "," +
                CommonUtils.getCurrentTimestamp() + "," +
                responseBody.length() + "," +
                responseBody + "]";
    }

    /**
     * 解析位置数据
     * [867387060179523,89860121801328840281,202308041624300007,GE
     * T_WEATHER_INFO,3,20230804162430,191,2E0.000000N0.000000T202
     * 30804162430@460!0!30589!218936329@wifi!58:41:20:FD:1C:CD!-7
     * 3#wifi!E2:ED:90:6F:FE:22!-74#wifi!A8:3B:5C:5B:39:BC!-80#wif
     * i!C0:E3:FB:8B:19:73!-87#wifi!C0:E3:FB:8B:19:70!-87]
     * <p>
     * GPS 位置信息@LBS 数据@WIFI 数据 字段说明如下：
     * GPS 位置信息：遵循 NEMA 报文格式 GPS 上报 位置信息，
     * 参见附录 A；
     * 460,0,9231,2351,-30: LBS 基站数据,MCC 国
     * 家码,460 为中国,0:MNC,0为移动, 9231:LAC, 十进制,
     * 2351,CID,十进制
     * 如 果 GPS 数据包中状态为 1, 或 者 经 纬 度 为 ”
     * 0000.0000N00000.0000E ” 时 , 则 取 LBS 数 据
     * wifi!AC:BC:32:78:A2:5F!-97: 一组 WIFI 信 息，wifi 为
     * SSID，AC:BC:32:78:A2:5F 为 MAC 地址，-97 为信号强度
     * ，变量之间用“ !”分隔开WIFI信 息可以有多组，每组之
     * 间用“#”分隔
     */
    public SysDeviceLocation parseLocationData(SysDevice device, String body, String timestamp) {

        String data = body.split("@")[0];

        /*需要处理的数据格式为 2E0.000000N0.000000T20230804162430*/
        /*第一位为定位状态，“0”：表示定位成功， “1”：表示定位失败， 2”：表示GPS 未打开， 或 GPS位置暂不用等其它 情况*/
        if (!StringUtils.startsWith(data, "0")) {
            return null;
        }

        SysDeviceLocation location = new SysDeviceLocation();
        location.setDeviceId(device.getDeviceId());
        location.setDeviceIdentifier(device.getDeviceIdentifier());
        location.setUserId(device.getBindUserId());
        location.setCreateTime(new Date());

        AppUser user = appUserService.selectAppUserById(device.getBindUserId());
        if (Objects.nonNull(user)) {
            location.setUserName(user.getLoginName());
        }


        // 定义正则表达式模式
        String pattern = "([0-9])E([0-9.]+)N([0-9.]+)T(\\d{14})";
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(data);

        if (m.find()) {

            // 提取经纬度和时间
            String status = m.group(1);
            if ("0".equals(status)) {
                double longitude = Double.parseDouble(m.group(2));
                double latitude = Double.parseDouble(m.group(3));
                // 解析时间字符串
                DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
                Date date;
                try {
                    date = dateFormat.parse(timestamp);
                } catch (ParseException e) {
                    date = new Date();
                }
                location.setLongitude(longitude);
                location.setLatitude(latitude);
                location.setLocationType("GPS");
                location.setLocationTime(date);
            } else {
                log.error("设备：{}定位失败{}", device.getDeviceIdentifier(), body);
                return null;
            }
        } else {
            log.error("位置数据解析失败：{}", body);
            return null;
        }
        return location;
    }

    @Override
    public String getCommandType() {
        return "REPORT_LOCATION_INFO";
    }
}